﻿/*======================================
作者：洞庭夕照
创建：2017.8.23
网站：www.ninesky.cn
      mzwhj.cnblogs.com
代码：git.oschina.net/ninesky/Ninesky
版本：v1.0.0.0
======================================*/
using Microsoft.EntityFrameworkCore;
using Ninesky.DBLibrary;
using Ninesky.IService;
using Ninesky.Models;
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;

namespace Ninesky.Service
{
    /// <summary>
    /// 内容服务
    /// </summary>
    public class ContentService:BaseService<Content>, IContentService
    {
        /// <summary>
        /// 栏目服务
        /// </summary>
        private CategoryService _categoryService { get; set; }

        /// <summary>
        /// 文章服务
        /// </summary>
        private ArticleService _articleService { get; set; }

        public ContentService(NsDbContext nsDbContext):base(nsDbContext)
        {
            _categoryService = new CategoryService(nsDbContext);
            _articleService = new ArticleService(nsDbContext);
        }

        public override  async Task<OperationResult> AddAsync(Content entity, bool isSave = true)
        {
            OperationResult opsResult = new OperationResult { Succeed = true, Message = "添加内容成功" };
            //验证栏目是否可以添加指定内容
            //查找所属栏目
            var category = await _categoryService.FindAsync(entity.CategoryId);
            if (category == null)
            {
                opsResult.Succeed = false;
                opsResult.Message = "栏目不存在";
            }
            else if (category.Type != CategoryType.General)
            {
                opsResult.Succeed = false;
                opsResult.Message = "栏目不能添加内容";
            }
            else if(category.ModuleType != entity.ModuleType)
            {
                opsResult.Succeed = false;
                opsResult.Message = "选择的栏目不能添加当前类型的内容";
            }
            else
            {
                switch (entity.ModuleType)
                {
                    case ModuleType.Article:
                        return await AddArticleAsync(entity, isSave);
                    default:
                        opsResult.Succeed = false;
                        opsResult.Message = "内容类型未知";
                        break;
                }
            }
            return opsResult;
        }

        public async Task<OperationResult> AddArticleAsync(Content entity, bool isSave = true)
        {
            OperationResult opsResult = new OperationResult { Succeed = true, Message = "添加文章成功" };
            if(entity.Article == null)
            {
                opsResult.Succeed = false;
                opsResult.Message = "文章实体为空";
            }
            else opsResult = await base.AddAsync(entity, isSave);
            return opsResult;
        }

        /// <summary>
        /// 查找内容【包含外键】
        /// </summary>
        /// <param name="predicate">查询表达式</param>
        /// <returns></returns>
        public async override Task<Content> FindAsync(int id)
        {
            var content = await NsDbContext.Set<Content>().AsNoTracking().Include(c => c.Article).SingleOrDefaultAsync(c => c.ContentId == id);
            //if (content != null)
            //{
            //    switch (content.ModuleType)
            //    {
            //        case ModuleType.Article:
            //            //content.Article = await _articleService.FindByContentId(content.ContentId);
            //            break;
            //    }
            //}
            return content;
        }

        /// <summary>
        /// 查询实体分页数据
        /// </summary>
        /// <param name="predicate">查询条件</param>
        /// <param name="keySelector">排序字段属性表达式</param>
        /// <param name="isAsc">是否正序</param>
        /// <param name="paging">分页数据</param>
        /// <returns>分页数据</returns>
        public async Task<Paging<ContentItem>> FindPagingAsync<TKey>(Expression<Func<Content, bool>> predicate, Expression<Func<Content, TKey>> keySelector, bool isAsc, Paging<ContentItem> paging)
        {
            var entityList = NsDbContext.Set<Content>().Include("Category").AsNoTracking<Content>().Where(predicate);
            paging.Total = await entityList.CountAsync();
            if (isAsc) entityList = entityList.OrderBy(keySelector);
            else entityList.OrderByDescending(keySelector);
            paging.Entities = await entityList.Skip((paging.PageIndex - 1) * paging.PageSize).Take(paging.PageSize).Select(c => new ContentItem() {
                CategoryId = c.CategoryId,
                CategoryName = c.Category.Name,
                ContentId = c.ContentId,
                CreateTime = c.CreateTime,
                DefaultPicUrl = c.DefaultPicUrl,
                Hits = c.Hits,
                Inputer = c.Inputer,
                LinkUrl = c.LinkUrl,
                ModuleType = c.ModuleType,
                Status = c.Status,
                Title = c.Title
            }).ToListAsync();
            return paging;
        }

        /// <summary>
        /// 查询内容分页数据
        /// </summary>
        /// <param name="categoryId">栏目ID</param>
        /// <param name="type">内容类型</param>
        /// <param name="title">标题</param>
        /// <param name="inputer">录入者</param>
        /// <param name="status">状态</param>
        /// <param name="order">排序</param>
        /// <param name="paging">分页</param>
        /// <returns></returns>
        public async Task<Paging<ContentItem>> FindPagingAsync(int categoryId,ModuleType type,string title, string inputer,ContentStatus? status,ContentOrder? order,Paging<ContentItem>paging)
        {
            var entityList = NsDbContext.Set<Content>().Include("Category").AsNoTracking<Content>();
            if (categoryId > 0) entityList = entityList.Where(c => c.CategoryId == categoryId);
            if(Enum.IsDefined(typeof(ModuleType), type)) entityList = entityList.Where(c => c.ModuleType == type);
            if (!string.IsNullOrEmpty(title)) entityList = entityList.Where(c => c.Title.Contains(title));
            if(!string.IsNullOrEmpty(inputer)) entityList = entityList.Where(c => c.Inputer == inputer);
            if(status != null) entityList = entityList.Where(c => c.Status == status);
            paging.Total = await entityList.CountAsync();
            if (order != null)
            {
                switch (order)
                {
                    case ContentOrder.IdAsc:
                        entityList = entityList.OrderBy(c => c.ContentId);
                        break;
                    case ContentOrder.IdDesc:
                        entityList = entityList.OrderByDescending(c => c.ContentId);
                        break;
                    case ContentOrder.UpdatedAsc:
                        entityList = entityList.OrderBy(c => c.CreateTime);
                        break;
                    case ContentOrder.UpdatedDesc:
                        entityList = entityList.OrderByDescending(c => c.CreateTime);
                        break;
                    case ContentOrder.HitsAsc:
                        entityList = entityList.OrderBy(c => c.Hits);
                        break;
                    case ContentOrder.HitsDesc:
                        entityList = entityList.OrderByDescending(c => c.Hits);
                        break;
                    default:
                        entityList = entityList.OrderByDescending(c => c.ContentId);
                        break;
                }
            }
            else entityList = entityList.OrderByDescending(c => c.ContentId);
          
            paging.Entities = await entityList.Skip((paging.PageIndex - 1) * paging.PageSize).Take(paging.PageSize).Select(c => new ContentItem()
            {
                CategoryId = c.CategoryId,
                CategoryName = c.Category.Name,
                ContentId = c.ContentId,
                CreateTime = c.CreateTime,
                DefaultPicUrl = c.DefaultPicUrl,
                Hits = c.Hits,
                Inputer = c.Inputer,
                LinkUrl = c.LinkUrl,
                ModuleType = c.ModuleType,
                Status = c.Status,
                Title = c.Title
            }).ToListAsync();
            return paging;
        }

        public async override Task<OperationResult> UpdateAsync(Content entity, bool isSave = true)
        {
            OperationResult opsResult = new OperationResult { Succeed = true, Message = "修改内容成功" };
            //验证栏目是否可以保存指定内容
            //查找所属栏目
            var category = await _categoryService.FindAsync(entity.CategoryId);
            if (category == null)
            {
                opsResult.Succeed = false;
                opsResult.Message = "栏目不存在";
            }
            else if (category.Type != CategoryType.General)
            {
                opsResult.Succeed = false;
                opsResult.Message = "栏目不能保存内容";
            }
            else if (category.ModuleType != entity.ModuleType)
            {
                opsResult.Succeed = false;
                opsResult.Message = "选择的栏目不能保存当前类型的内容";
            }
            else
            {
                switch (entity.ModuleType)
                {
                    case ModuleType.Article:
                        return await UpdateArticleAsync(entity, isSave);
                    default:
                        opsResult.Succeed = false;
                        opsResult.Message = "内容类型未知";
                        break;
                }
            }
            return opsResult;
        }

        public async Task<OperationResult> UpdateArticleAsync(Content entity, bool isSave = true)
        {
            OperationResult opsResult = new OperationResult { Succeed = true, Message = "更新文章成功" };
            if (entity.Article == null)
            {
                opsResult.Succeed = false;
                opsResult.Message = "文章数据为空";
            }
            else
            {
                var content = await FindAsync(entity.ContentId);
                if(content == null)
                {
                    opsResult.Succeed = false;
                    opsResult.Message = "内容不存在，请确认是否已经删除";
                }
                else
                {
                    
                    content.CategoryId = entity.CategoryId;
                    content.ContentId = entity.ContentId;
                    content.CreateTime = entity.CreateTime;
                    content.DefaultPicUrl = entity.DefaultPicUrl;
                    content.Hits = entity.Hits;
                    content.LinkUrl = entity.LinkUrl;
                    content.ModuleType = entity.ModuleType;
                    content.Status = entity.Status;
                    content.Title = entity.Title;
                    content.Article.Author = entity.Article.Author;
                    content.Article.Content = entity.Article.Content;
                    content.Article.Intro = entity.Article.Intro;
                    content.Article.Keyword = entity.Article.Keyword;
                    content.Article.Source = entity.Article.Source;
                   opsResult =  await base.UpdateAsync(content);
                }
            }
            return opsResult;
        }
    }
}
